﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Casamiel.API.Application;
using Casamiel.API.Application.Commands;
using Casamiel.API.Application.Models;
using Casamiel.API.Application.Models.ICModels;
using Casamiel.API.Application.Services;
using Casamiel.API.Controllers;
using Casamiel.API.Infrastructure;
using Casamiel.API.Infrastructure.Filters;
using Casamiel.API.Infrastructure.Wxpay;
using Casamiel.Application;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Casamiel.Domain.Entity;
using Casamiel.Domain.Request;
using Casamiel.Domain.Response;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;

namespace Casamiel.Controllers
{

    /// <summary>
    /// 支付接口
    /// </summary>
    [Produces("application/json")]
    [Route("api/v{api-version:apiVersion}/Pay")]
    //[Authorize]
    [ApiController]
    public class PaymentController : BaseController
    {
        private ICacheService _cacheService;
        private readonly string outTradeNo = "C" + DateTime.Now.ToString("yyyyMMddHHmmssffff", CultureInfo.CurrentCulture);
        private readonly NLog.ILogger logger = LogManager.GetLogger("BizInfo");
        private readonly IPaymentService _paymentService;
        private readonly IMediator _mediator;
        private readonly IIcApiService _iicApiService;
        private readonly string _apitoken;
        private readonly IUserLogService _userLog;
        private readonly IMemberCardRepository _memberCard;
        
        private readonly CasamielSettings _settings;
        private readonly WxPaySettigs _wxPaySettigs;
        private readonly HttpClient _httpClient;
        private readonly IPayGateWayService _payGateWayService;
        private readonly IStoreService _storeService;
        private readonly IWxService _wxLogin;
        /// <summary>
        /// Initializes a new instance of the <see cref="T:Casamiel.Controllers.PaymentController"/> class.
        /// </summary>
        /// <param name="settings">Settings.</param>
        /// <param name="optionsSnapshot">Options snapshot.</param>
        /// <param name="payment">Payment.</param>
        /// <param name="iicApiService">Iic API service.</param>
        /// <param name="cacheService">Cache service.</param>
        /// <param name="userLog">User log.</param>
        /// <param name="memberCard">Member card.</param>
        /// <param name="wxService">Wxpay temp.</param>
        /// <param name="payGateWayService">Pay gate way service.</param>
        /// <param name="storeService"></param>
        /// <param name="mediator"></param>
        public PaymentController(IOptionsSnapshot<CasamielSettings> settings, IOptionsSnapshot<WxPaySettigs> optionsSnapshot
            , IPaymentService payment,
            IIcApiService iicApiService, ICacheService cacheService,
            IUserLogService userLog,
            IMemberCardRepository memberCard,
             IPayGateWayService payGateWayService,
             IWxService wxService,
            IStoreService storeService, IMediator mediator)
        {
            if (settings == null) {
                throw new ArgumentNullException(nameof(settings));
            }

            if (optionsSnapshot == null) {
                throw new ArgumentNullException(nameof(optionsSnapshot));
            }

            _wxPaySettigs = optionsSnapshot.Value;
            // _gateways = gateways;
            this._paymentService = payment;
            _cacheService = cacheService;
            _iicApiService = iicApiService;
            _userLog = userLog;
            _memberCard = memberCard;
            _settings = settings.Value;
            _wxLogin = wxService;
            _httpClient = new HttpClient();
            _httpClient.Timeout = new TimeSpan(0, 0, 30);
            _httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");
            this._payGateWayService = payGateWayService;
            _storeService = storeService;
            _mediator = mediator;
            _apitoken = settings.Value.ApiToken;
        }
 
        /// <summary>
        /// app端发起支付请求
        /// </summary>
        /// <param name="data"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        [TypeFilterAttribute(typeof(CheckLoginAttribute))]
        public async Task<IActionResult> PaymentRequest([FromBody] PaymentReq data, [FromHeader(Name = "u-token")] string token)
        {
             if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var content = "";
            var mobile = MemberHelper.GetMobile(token);
            if (_settings.IsTest) {
                var tester = await _paymentService.GetAllTesterAsync<ICasaMielSession>().ConfigureAwait(false);
                if (tester.Where(a => a.Mobile == mobile).Count() == 1) {
                    var tentity = tester.Where(a => a.Mobile == mobile).SingleOrDefault();
                    data.chargemoney = tentity.chargemoney;
                }
            }

            if (data.operationMethod == 1) {
                var list = await _memberCard.GetListAsync<ICasaMielSession>(mobile).ConfigureAwait(false);
                
                var mcard = list.Where(a => a.IsBind == true && a.CardNO.Contains(data.billNO)).FirstOrDefault();
                // var mcard = _cacheService.Get<MemberCard>("c_" + token);
                if (mcard != null) {
                    var a = await _iicApiService.GetCardBalance(data.billNO, $"{LoginInfo.Item3}099".ToInt32(0)).ConfigureAwait(false);
                    var rnt = JsonConvert.DeserializeObject<JObject>(a.content);
                    if (a.code == 0) {
                        var je = Convert.ToDouble(rnt["totalmoney"].ToString(), CultureInfo.CurrentCulture);
                        if ((je + data.chargemoney) > 2500) {
                            return new JsonResult(new { code = -1, content = "", msg = $"最多还能充值{(2500 - je).ToString("C2", CultureInfo.CurrentCulture)}" });
                        }
                    } else {
                        if (data.chargemoney > 2500) {
                            return new JsonResult(new { code = -1, content = "", msg = $"最多还能充值{(2500).ToString("C2", CultureInfo.CurrentCulture)}" });
                        }
                    }
                } else {
                    return new JsonResult(new { code = -1, content = "", msg = "无此卡" });
                }
            }
            var shopname = "";
            if (data.shopId.HasValue && data.shopId > 0) {
                var store = await _storeService.GetByRelationIdAsync<ICasaMielSession>(data.shopId.Value).ConfigureAwait(false);
                if (store != null) {
                    shopname = store.StoreName;
                }
            }
            switch (data.paytype) {
                case 2:
                    content = _payGateWayService.CreateAlipayOrder(outTradeNo, data.chargemoney, shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateAlipayOrder(data);
                    data.summary = "app支付宝支付";
                    break;
                case 1:
                    content = _payGateWayService.CreateWechatpayOrder(outTradeNo, data.chargemoney, shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateWechatpayOrder(data);
                    data.summary = "app微信支付";
                    break;
                case 4:
                    WxOpenId wxloginentity = null;
                    var list = await _wxLogin.GetMiniAppSettingsList<ICasaMielSession>().ConfigureAwait(false);
                    var item = list.Find(c => c.AppId == "wx2664f95341432616");
                    if (item != null)
                    {
                        wxloginentity = await _wxLogin.GetByAppIdMobileAsync<ICasaMielSession>(item.AppId, mobile).ConfigureAwait(false);
                    }
                    if (wxloginentity == null)
                    {
                        throw new ArgumentException("openid不存在");
                    }
                    content = _payGateWayService.CreateMiniWechatpayOrder(outTradeNo, data.chargemoney, wxloginentity.OpenId, "wxd28310a576274ea3", shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateMiniWechatpayOrder(data);
                    data.summary = "微信小程序支付";
                    break;
                default:
                    break;
            }
            var payment = new PaymentRecord() {
                Mobile = data.mobile,
                BillNO = data.billNO,
                OperationMethod = 1,
                Amount = data.chargemoney,
                CreateTime = DateTime.Now,
                ShopId = data.shopId,
                TradeNo = outTradeNo,
                PayMethod = data.paytype,
                Remark = data.summary
            };
            await _paymentService.AddAsync<ICasaMielSession>(payment).ConfigureAwait(false);
            //  var ad = await _paymentRecordRepository.UnitOfWork.SaveEntitiesAsync();
            return new JsonResult(new { code = 0, content = content });
        }
        /// <summary>
        /// app调用
        /// </summary>
        /// <param name="data"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        [TypeFilterAttribute(typeof(CheckLoginAttribute))]
        public async Task<IActionResult> PaySuccess([FromBody] PaySuccessReq data, [FromHeader(Name = "u-token")] string token)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var entity = _paymentService.FindAsync<ICasaMielSession>(data.tradeNo);
            entity.Wait();
            var payrecord = entity.Result;
            if (payrecord == null) {
                return BadRequest();
            }
            if (payrecord.State == 0) {
                if (payrecord.Amount == data.amount && payrecord.OutTradeNo == data.outTradeNO) {
                    if (payrecord.OperationMethod == 1)//充值
                    {
                        Zmodel tmodel = await _iicApiService.IcCharge(payrecord.BillNO, payrecord.Amount, payrecord.PayMethod, payrecord.OutTradeNo, "").ConfigureAwait(false);
                        if (tmodel.code == 0 || tmodel.code == 180) {
                            var rnt = JsonConvert.DeserializeObject<dynamic>(tmodel.content);
                            payrecord.IcTradeNO = rnt.tradeno;
                            payrecord.PayTime = DateTime.Now;
                            payrecord.OperationState = 1;
                            payrecord.LastOperationTime = DateTime.Now;
                            await _paymentService.UpdateAsync<ICasaMielSession>(payrecord).ConfigureAwait(false);
                            //var success =  await _paymentRecordRepository.UnitOfWork.SaveChangesAsync();
                            // if (success > 0)
                            // {
                            var logdata = new UserLog { Url = Request.GetShortUri(), OPInfo = $"会员充值，卡号[{payrecord.BillNO}],金额{payrecord.Amount}", OPTime = DateTime.Now, UserName = payrecord.Mobile, UserIP = Request.GetUserIp() };
                            await _userLog.AddAsync<ICasaMielSession>(logdata).ConfigureAwait(false);
                            // }
                        } else {
                            return new JsonResult(new { code = -1, content = "", msg = "出错了" });
                        }
                    }
                }
            }

            return new JsonResult(new { code = 0, content = new { amount = payrecord.Amount }, msg = "支付成功" });
        }



     
       
        private static string GenerateRandomCode(int length)
        {
            var result = new StringBuilder();
            for (var i = 0; i < length; i++) {
                if (i == 0) {
                    Console.WriteLine(Guid.NewGuid().GetHashCode());
                    var r = new Random(Guid.NewGuid().GetHashCode());
                    result.Append(r.Next(1, 10));
                } else {
                    var r = new Random(Guid.NewGuid().GetHashCode());
                    result.Append(r.Next(0, 10));
                }
            }
            return result.ToString();
        }

       

    }
}